// Require
var watchr = require('watchr');
var winston = require('winston');
var exec = require('child_process').exec;
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));
var path = require('path');

var config = {
    scriptPath: __dirname + '/processImage.js',
    watchPath: path.join(__dirname, "..",  'ftpUpload'),
    logPath: path.join(__dirname, "..",  'log', 'wpwatch.log')
}

var lastWatchDirectory = getLastDirectory(config.watchPath);
var reEventId = new RegExp(lastWatchDirectory + "\\/\(\\d+\)\\/");
var reImage = /(jpeg|jpg|png)$/i;


winston.add(winston.transports.File, { filename: config.logPath, timestamp: function(){ return new Date().toTimeString()}});

// Watch a directory or file
console.log('Watch our paths: ' + config.watchPath);
console.log('script path: ' + config.scriptPath);
console.log('log path: ' + config.logPath);
watchr.watch({
    paths: [config.watchPath],
    listeners: {
        watching: function(err,watcherInstance,isWatching){
            if (err) {
                console.log("watching the path " + watcherInstance.path + " failed with error", err);
            } else {
                console.log("watching the path " + watcherInstance.path + " completed");
            }
        },
        change: function(changeType,filePath,fileCurrentStat,filePreviousStat){
            if(changeType == "create"){
                var matchEventId, eventId;
                matchEventId = filePath.match(reEventId);
                if(matchEventId && matchEventId.length > 1){
                    eventId = matchEventId[1];
                    searchImages(filePath, eventId);
                }
                
            }

        }
    },
    next: function(err,watchers){
        if (err) {
            return console.log("watching everything failed with error", err);
        } else {
            console.log('watching everything completed', watchers);
        }

        
    }
});


function searchImages(filePath, eventId){
    if(reImage.test(filePath)){

        isImgCompleted(filePath, eventId, 6);
        
    }else{
        fs.stat(filePath, function(err,stats){
            if(err){
                winston.err("failed to get path stat info -- " , err);
            }

            if(stats.isDirectory()){
                winston.info("Directory: " + filePath);
                fs.readdir(filePath, function(err, files){
                    if(err){
                        winston.err("failed to read file form " + filePath, err);
                    }
                    if(files && files.length > 0){
                        for(var i = 0, l = files.length; i < l; i++){
                            searchImages(path.join(filePath, files[i]), eventId);
                        }
                    }
                });
            }else{
                winston.info("File: " + filePath);
            }
        });
    }
    

}

function getLastDirectory(path){
    var length = path.length;
    var lastIndex = path.lastIndexOf("/");
    if(length == lastIndex + 1){
        path = path.substr(0,lastIndex);
        lastIndex = path.lastIndexOf("/");
    }

    return path.substr(lastIndex + 1);
}

function isImgCompleted(pathToImg, eventId, tryTimes){
    fs.readFileAsync(pathToImg)
        .then(function(data){
            data = data.toString('hex');
            data = data.substr(data.length - 4);
            if(data == "ffd9" || data == "6082"){
                ipq.enQueue({'filePath':pathToImg, 'eventId':eventId});
            }else{
                if(tryTimes > 0){
                    tryTimes--
                    winston.error(pathToImg + " is not completed. Will try another time 30 seconds later. times " + tryTimes);
                    setTimeout(function(){
                        isImgCompleted(pathToImg, eventId, tryTimes);
                    }, 30000)   
                }
            }
        })
        .catch(function(err){
            winston.error("isImgCompleted error " + err);
        });
}

var ImageProcessQueue = function(){
    this.queue = [];
    this.idle = true;
    this.looping = false;
    this.loopTimeHandle = null;
}

ImageProcessQueue.prototype.isLooping = function(){
    return this.looping;
}

ImageProcessQueue.prototype.loop = function(){
    var self = this;
    self.loopTimeHandle = setTimeout(function(){
        self.loop();
    }, 500);
    self.checkJob();
}

ImageProcessQueue.prototype.unLoop = function(){
    clearTimeout(this.loopTimeHandle);
    this.loopTimeHandle = null;
    this.looping = false;
}

ImageProcessQueue.prototype.enQueue = function(item){
    this.queue.push(item);
    if(!this.isLooping()){
        this.loop();
        this.looping = true;
    }
    return this;
}

ImageProcessQueue.prototype.deQueue = function(){
    if(this.queue.length > 0){
        return this.queue.shift();
    }else{
        this.unLoop();
        return false;
    }
}

ImageProcessQueue.prototype.checkJob = function(){
    winston.info("image process queue is checking job ....");
    this.idle && this.dispatchJob(this.deQueue());
}

ImageProcessQueue.prototype.dispatchJob = function(job){
    if(!job)
        return
    var self = this;
    self.idle = false;
    var filePath = job.filePath;
    var eventId = job.eventId;
    var cmd = "node " + config.scriptPath + " '" + filePath + "' " +eventId;
    winston.info("Going to process: " + filePath + " eventId: " + eventId);
    exec(cmd, function(err, stdout, stderr){
        if(err){
            winston.error("failed to process image", err);
        }
        if(stderr){
            winston.error(stderr);  
        }else{
            winston.info("process image completed.");
        }
        self.idle = true;
    });

}
var ipq = new ImageProcessQueue();